/**
 * 顾名思义，就是给定一个时间，如果接口请求超过这个时间的话就报错
 * 
 * 接口请求和延时函数赛跑，并使用一个Promise包着，
 * 由于Promise的状态是不可逆的，所以如果 接口请求先跑完 则说明 未超时 且 Promise的状态是fulfilled，
 * 反之，延时函数先跑完 则说明超时了且Promise的状态是rejetced，最后根据Promise的状态来判断有无超时
*/
/**
 * 模拟延时
 * @param {number} delay 延迟时间
 * @returns {Promise<any>}
 */
function sleep(delay) {
    return new Promise((_, reject) => {
        setTimeout(() => reject('超时喽'), delay)
    })
}

/**
 * 模拟请求
 */
function request() {
    // 假设请求需要 1s
    return new Promise(resolve => {
        setTimeout(() => resolve('成功喽'), 1000)
    })
}

/**
 * 判断是否超时
 * @param {() => Promise<any>} requestFn 请求函数
 * @param {number} delay 延迟时长
 * @returns {Promise<any>}
 */
function timeoutPromise(requestFn, delay) {
    return new Promise((resolve, reject) => {
        const promises = [requestFn(), sleep(delay)]
        for (const promise of promises) {
            // 超时则执行失败，不超时则执行成功
            promise.then(res => resolve(res), err => reject(err))
        }
    })
}

//timeoutPromise 方法中的代码可以使用 Promise.race 来代替，是同样的效果
function timeoutPromise(requestFn, delay) {
    // 如果先返回的是延迟Promise则说明超时了
    return Promise.race([requestFn(), sleep(delay)])
}

// 超时
timeoutPromise(request, 500).catch(err => console.log(err)) // 超时喽

// 不超时
timeoutPromise(request, 2000).then(res => console.log(res)) // 成功喽